package controllers

import (
	"fmt"
	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
	"goravel/app/models"
	"goravel/app/services"
	"goravel/app/types"
	"strconv"
	"time"
)

type AuthController struct {
	DbServer services.DBServer
}

func NewAuthController() *AuthController {
	return &AuthController{
		DbServer: services.NewDBService(),
	}
}

// Captcha 获取图形验证码
// @Summary      获取图形验证码
// @Tags         Auth
// @Router       /auth/captcha [get]
func (c *AuthController) Captcha(ctx http.Context) http.Response {
	id, b64s, answer, err := services.NewCaptchaService().Generate()
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	fmt.Println(id, answer)
	return services.NewApiService(ctx).Data(http.Json{
		"code":       id,
		"base64code": b64s,
	})
}

// Login 后台登录
// @Summary      后台登录
// @Tags         Auth
// @Router       /auth/login [post]
func (r *AuthController) Login(ctx http.Context) http.Response {
	var err error
	var loginReq types.AuthLoginReq
	err = ctx.Request().Bind(&loginReq)
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	validateErr, err := services.NewApiService(ctx).Validate(&loginReq)
	if err != nil {
		return services.NewApiService(ctx).Error500("参数验证错误", services.WithErrors(validateErr))
	}
	// 验证码验证
	result := services.NewCaptchaService().Verify(loginReq.CaptchaId, loginReq.CaptchaAnswer, true)
	if !result {
		return services.NewApiService(ctx).Error500("验证码错误")
	}
	var user models.SysUser
	err = facades.Orm().Query().Where("name", loginReq.UserName).FirstOrFail(&user)
	if err != nil {
		return services.NewApiService(ctx).Error500("用户名或密码错误")
	}
	if !facades.Hash().Check(loginReq.Password, user.Password) {
		return services.NewApiService(ctx).Error500("用户名或密码错误")
	}
	var token string
	token, err = facades.Auth(ctx).Login(&user)
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	// TODO: 将token存入缓存，如果需要踢出登录，则可以从缓存中删除token
	jwtTtl := facades.Config().GetInt("auth.jwt.ttl")
	_ = facades.Cache().Put("jwt_token:"+token, 1, time.Duration(jwtTtl)*time.Second)
	fmt.Println("jwt_token:" + token)

	// 插入login_log
	loginLog := models.LoginLog{
		UserId:    int64(user.ID),
		UserName:  user.Name,
		LoginIp:   ctx.Request().Ip(),
		UserAgent: ctx.Request().Header("User-Agent"),
	}
	_ = facades.Orm().Query().Create(&loginLog)
	return services.NewApiService(ctx).Data(http.Json{
		"token": token,
	})
}

// RefreshToken 刷新后台token
// @Summary      刷新token
// @Tags         Auth
// @Router       /auth/refresh [post]
func (r *AuthController) RefreshToken(ctx http.Context) http.Response {
	var err error
	var token string
	sysUser := models.SysUser{}
	err = facades.Auth(ctx).User(&sysUser)
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	fmt.Println("sysUser:", sysUser.Name)
	token, err = facades.Auth(ctx).Refresh()
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	return services.NewApiService(ctx).Data(http.Json{
		"token": token,
	})
}

// Logout 退出后台登录
// @Summary      退出后台登录
// @Tags         Auth
// @Router       /auth/logout [post]
func (r *AuthController) Logout(ctx http.Context) http.Response {
	_ = facades.Auth(ctx).Logout()
	// TODO: 从缓存中删除token
	return services.NewApiService(ctx).OK("")
}

// Info 获取我的详情
// @Summary      我的详情
// @Tags         User
// @Router       /auth/info [get]
func (r *AuthController) Info(ctx http.Context) http.Response {
	var err error
	idStr, err := facades.Auth(ctx).ID()
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		return services.NewApiService(ctx).Error500("用户未登录")
	}
	var user models.SysUser
	var userResp types.AuthUserInfoResp
	data, err := r.DbServer.GetById(&user, &userResp, id)
	if err != nil {
		return services.NewApiService(ctx).Error500(err.Error())
	}
	userResp.Roles = []string{"admin"}
	return services.NewApiService(ctx).Data(data)
}

// Edit 修改我的资料
// @Summary      修改我的资料
// @Tags         User
// @Router       /auth/edit [put]
func (r *AuthController) Edit(ctx http.Context) http.Response {
	// TODO: 实现修改我的资料
	return services.NewApiService(ctx).OK("接口开发中")
}
